/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Initial Developer of the Original Code is
*   Nick Kreeger
* Portions created by the Initial Developer are Copyright (C) 2006-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*   Nick Kreeger <nick.kreeger@park.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

#import "MailWindowController.h"

#import "CHMsgService.h"
#import "MessageWindowService.h"
#import "MessageComposeService.h"
#import "MessageListDataSource.h"
#import "CompositionWindowController.h"
#import "MessageWindowController.h"
#import "MailboxesOutlineView.h"
#import "MailboxesDataSource.h"
#import "MessagesDataSource.h"
#import "NotificationHandler.h"
#import "MailboxTextCell.h"
#import "MailboxItem.h"
#import "MessageAccount.h"
#import "MessageAccountManager.h"
#import "DummyMessageHeader.h"
#import "MessageHeaderView.h"
#import "BrowserTabView.h"
#import "BrowserTabViewItem.h"
#import "PreferenceManager.h"
#import "KeychainService.h"
#import "AttachmentView.h"
#import "AddressBookDlgController.h"
#import "MessageViewContainer.h"
#import "GradientSplitView.h"

// Toolbar Identifiers
static NSString* const kMailWindowToolbarIdentifier = @"MailWindowToolbarIdentifier";
static NSString* const kNewMessageToolbarIdentifier = @"NewMessageToolbarIdentifier";
static NSString* const kDeleteMailToolbarIdentifier = @"DeleteMailToolbarIdentifier";
static NSString* const kReplyToolbarIdentifier = @"ReplyToolbarIdentifier";
static NSString* const kReplyAllToolbarIdentifier = @"ReplyAllToolbarIdentifier";
static NSString* const kFowardToolbarIdentifier = @"FowardToolbarIdentifier";
static NSString* const kSendReceiveToolbarIdentifier = @"SendReceiveToolbarIdentifier";
static NSString* const kStopToolbarIdentifier = @"StopToolbarIdentifier";
static NSString* const kAddressBookToolbarIdentifier = @"AddressBookToolbarIdentifier";

// Table Identifiers
static NSString* const kMailboxesTableColumnIdentifier = @"MailboxesIdentifier";

// Sizing saving
static NSString* const kMailWindowFrameSaveName = @"MailWindow";
static NSString* const kMailboxOutlineViewWidth = @"MailboxOutlineViewWidth";
static NSString* const kMessageViewSize = @"MessagesViewSize";
static NSString* const kIsMessageSplitViewVertical = @"IsMessageSplitViewVertical";
static NSString* const kSortedTableColumn = @"SortedTableColumn";
static NSString* const kIsMessageListSortedDescending = @"IsMessageListSortedDescending";
static NSString* const kMessageFolderOpenCloseDictionary = @"MessageFolderOpenCloseDictionary";
static NSString* const kMessageFolderIsOpenState = @"MessageFolderIsOpenState";
static NSString* const kMessageFolderIsOpenStateKeySuffix = @"%@OpenState";

// Indentation level
static float const kIndentationLevel = 12.0;

#pragma mark -

@interface MailWindowController(Private)

-(void)setupToolbar;
-(CompositionWindowController*)newCompositionController;

-(void)refreshMailboxList;
-(void)updateMessageDisplay;
-(void)clearMessageView;

-(void)windowDidBecomeMain:(id)sender;
-(void)windowDidResignMain:(id)sender;

-(void)openMessageInNewWindow:(id)sender;

-(NSString*)formattedTitleWithCurrentFolder;

-(NSRect)calcFrameForWidth:(float)aWidth andFrame:(NSRect)aFrame;

// Browser Private methods:
-(BrowserTabViewItem*)openNewTab:(BOOL)aLoadInBG;

@end

@implementation MailWindowController

-(id)init
{
  if ((self = [super initWithWindowNibName:@"MailWindow"]))
  {
    mCurSelectedTableColumn = nil;
    mIsTransmitting = NO;
    mShouldAutosave = YES;
    mIsGettingNewMail = NO;
    mShouldRefreshFolder = NO;
  }
  
  return self;
}

-(void)dealloc
{
  [mMailboxesDataSource release];
  [mMessageListDataSource release];
  [mCHBrowserView release];
  [mMessageListDataSource release];
  [super dealloc];
}

-(void)awakeFromNib
{
  // Add the images to the messages table view.
  NSTableHeaderCell* flaggedCell = [[mMessagesTableView tableColumnWithIdentifier:@"isFlagged"] headerCell];
  NSTableHeaderCell* unreadCell = [[mMessagesTableView tableColumnWithIdentifier:@"isRead"] headerCell];
  [flaggedCell setImage:[NSImage imageNamed:@"flagcol.png"]];
  [unreadCell setImage:[NSImage imageNamed:@"readcol.png"]];
  
    // Get our saved dimensions.
  [[self window] setFrameAutosaveName:kMailWindowFrameSaveName];
  
  // Init the mailboxes data source
  mMailboxesDataSource = [[MailboxesDataSource alloc] init];
  [mMailboxesDataSource setMailboxesOutlineView:mMailboxesOutlineView];
  [mMailboxesOutlineView setDataSource:mMailboxesDataSource];
  [mMailboxesOutlineView setDelegate:self];
  
  // Reset the open/close state of folders
  NSDictionary* messageFolderDict = [[NSUserDefaults standardUserDefaults] objectForKey:kMessageFolderOpenCloseDictionary];
  if (messageFolderDict)
  {
    // Each folder is saved by account name?
    MailboxItem* curMailboxItem = nil;
    NSEnumerator* foldersEnum = [[mMailboxesDataSource rootAccountFolderList] objectEnumerator];
    while ((curMailboxItem = [foldersEnum nextObject]))
    {
      // Each mailbox's open state is saved using the |name| and the suffix "OpenState"
      NSNumber* savedValue = [messageFolderDict valueForKey:[NSString stringWithFormat:kMessageFolderIsOpenStateKeySuffix, [curMailboxItem name]]];
      if ([savedValue boolValue])
        [mMailboxesOutlineView expandItem:curMailboxItem];
    }
  }
  
  // This is temporary for now... This should be dynamically generated
  [mMessagesTableView setMenu:mMessagesTableViewMenu];
  
  // Update the message table view information
  mMessageListDataSource = [[MessageListDataSource alloc] initWithMailWindowController:self];
  [mMessagesTableView setDataSource:mMessageListDataSource];
  [mMessagesTableView setAutoresizesAllColumnsToFit:YES];  // this is deprecated in the 10.4 SDK
  [mMessagesTableView setAutosaveTableColumns:YES];
  NSEnumerator* colEnum = [[mMessagesTableView tableColumns] objectEnumerator];
  NSTableColumn* curCol = nil;
  while ((curCol = [colEnum nextObject]))
  {
    float savedColWidth = [[NSUserDefaults standardUserDefaults] floatForKey:[curCol identifier]];
    if (savedColWidth != 0)
      [curCol setWidth:savedColWidth];
  }
  
  [mMessageSplitView setVertical:[[NSUserDefaults standardUserDefaults] boolForKey:kIsMessageSplitViewVertical]];
  
  // Setup the mail window split view
  [mMailWindowSplitView setDelegate:self];
  NSView* outlineView = [[mMailWindowSplitView subviews] objectAtIndex:0];
  NSView* messagesView = [[mMailWindowSplitView subviews] objectAtIndex:1];
  
  NSRect outlineFrame = [outlineView frame];
  NSRect messagesFrame = [messagesView frame];
  NSRect splitViewFrame = [mMailWindowSplitView frame];
  float dividerThickness = [mMailWindowSplitView dividerThickness];
  float mailboxOutlineWidth = [[NSUserDefaults standardUserDefaults] floatForKey:kMailboxOutlineViewWidth];
  
  if (mailboxOutlineWidth > 0)
  {
    outlineFrame.size.width = mailboxOutlineWidth;
    messagesFrame.size.width = splitViewFrame.size.width - outlineFrame.size.width - dividerThickness;
    messagesFrame.origin.x = outlineFrame.size.width + dividerThickness;
    [outlineView setFrame:outlineFrame];
    [messagesView setFrame:messagesFrame];
  }
  
  // Setup the message window split view
  NSView* listView = [[mMessageSplitView subviews] objectAtIndex:0];
  NSView* messageView = [[mMessageSplitView subviews] objectAtIndex:1];
  
  NSRect listFrame = [listView frame];
  NSRect messageFrame = [messageView frame];
  splitViewFrame = [mMessageSplitView frame];
  dividerThickness = [mMessageSplitView dividerThickness];
  float messageViewSize = [[NSUserDefaults standardUserDefaults] floatForKey:kMessageViewSize];
  
  if (messageViewSize > 0)
  {
    if ([mMessageSplitView isVertical])
    {
      messageFrame.size.width = messageViewSize;
      listFrame.size.width = splitViewFrame.size.width - messageFrame.size.width - dividerThickness;
      listFrame.origin.x = messageFrame.size.width + dividerThickness;
      
      [listView setFrame:listFrame];
      [messageView setFrame:messageFrame];
    }
    else
    {
      messageFrame.size.height = messageViewSize;
      listFrame.size.height = splitViewFrame.size.height - messageFrame.size.height - dividerThickness;
      listFrame.origin.y = messageFrame.size.height + dividerThickness;
      [listView setFrame:listFrame];
      [messageView setFrame:messageFrame];
    }
  }
  
  // Set the saved sort configuration
  NSString* savedSortedColIdentifier = [[NSUserDefaults standardUserDefaults] objectForKey:kSortedTableColumn];
  mCurSelectedTableColumn = [mMessagesTableView tableColumnWithIdentifier:(savedSortedColIdentifier ? savedSortedColIdentifier : @"date")];
  BOOL sortDescending = [[NSUserDefaults standardUserDefaults] boolForKey:kIsMessageListSortedDescending];
  if (sortDescending)
    [self tableView:mMessagesTableView didClickTableColumn:mCurSelectedTableColumn];
  [self tableView:mMessagesTableView didClickTableColumn:mCurSelectedTableColumn];
}

-(void)windowDidLoad
{
  [super windowDidLoad];
  
  [[self window] setTitle:NSLocalizedString(@"AppName", nil)];
  [self setupToolbar];
  
  // remove the dummy tab view.
  //[mTabBrowser removeTabViewItem:[mTabBrowser tabViewItemAtIndex:0]];
  //[self createNewTab:eNewTabAboutBlank];
  
  // Setup the Mailboxes outline view
  NSTableColumn* mailBoxTableColumn = [mMailboxesOutlineView tableColumnWithIdentifier:kMailboxesTableColumnIdentifier];
  MailboxTextCell* mailBoxTextCell = [[[MailboxTextCell alloc] init] autorelease];
  [mailBoxTextCell setEditable:NO];  // Make sure
  [mailBoxTableColumn setDataCell:mailBoxTextCell];
  [mMailboxesOutlineView setIndentationPerLevel:kIndentationLevel];
  
  // Setup the messages view
  [mMessagesTableView setDataSource:mMessageListDataSource];
  [mMessagesTableView setDelegate:self];
  [mMessagesTableView setDoubleAction:@selector(openMessageInNewWindow:)];
  
  // Register for new account creations.
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(refreshMailboxList)
                                               name:kAccountRegistryChanged
                                             object:nil];
  // Create the browser view
  /*
  mBrowserWrapper = [[BrowserWrapper alloc] initWithFrame:[mBrowserView bounds] inWindow:[self window]];
  [mBrowserWrapper setDelegate:self];
   */
  //
  // For now use a CHBrowserView directly, this may not work so well since the subview doesn't resize
  // correctly. To make this work properly, make sure that tabs are working (most likely |BrowserWrapper|
  // is telling the browser view to hide since we don't have tabs).
  mCHBrowserView = [[CHBrowserView alloc] initWithFrame:[mBrowserView bounds] andWindow:[self window]];
  [mBrowserView setAutoresizesSubviews:YES];
  [mBrowserView setBrowserView:mCHBrowserView];
  
  // Load the welcome message
  NSString* welcomeFilePath = [[NSBundle mainBundle] pathForResource:@"welcome" ofType:@"html"];
  [mCHBrowserView loadURI:welcomeFilePath
                 referrer:nil 
                    flags:NSLoadFlagsNone 
              allowPopups:NO];
  
  // hack to make sure the border is drawn the first time
  [mBrowserView display];
   
  [[MessageWindowService sharedInstance] initMessageWindow:mCHBrowserView];
  
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(windowDidBecomeMain:) 
                                               name:NSWindowDidBecomeKeyNotification
                                             object:[self window]];
  
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(windowDidResignMain:) 
                                               name:NSWindowDidResignKeyNotification
                                             object:[self window]];
  
  // Notify the Global composer service that we are the current window controller.
  [[MessageComposeService sharedComposeService] setWindowController:self];
  
  MessageAccountManager* messageAccountMgr = [MessageAccountManager sharedInstance];
  [messageAccountMgr accountsExist];
  
  mCurMailboxItem = nil;
}

-(void)autosaveWindowFrame
{  
  // Save the table column widths.
  NSEnumerator* colEnum = [[mMessagesTableView tableColumns] objectEnumerator];
  NSTableColumn* curCol = nil;
  while ((curCol = [colEnum nextObject]))
    [[NSUserDefaults standardUserDefaults] setFloat:[curCol width] forKey:[curCol identifier]];
  
  // Save the pane widths
  [[NSUserDefaults standardUserDefaults] setFloat:[mMailboxesOutlineView frame].size.width
                                           forKey:kMailboxOutlineViewWidth];
  
  float tableViewSize = ([mMessageSplitView isVertical] ? [mBrowserView frame].size.width : [mBrowserView frame].size.height);
  //float tableViewSize = 20;
  [[NSUserDefaults standardUserDefaults] setFloat:tableViewSize forKey:kMessageViewSize];
  
  // Save current layout.
  [[NSUserDefaults standardUserDefaults] setBool:[mMessageSplitView isVertical]
                                          forKey:kIsMessageSplitViewVertical];
  
  // Save the current sort configuration.
  [[NSUserDefaults standardUserDefaults] setObject:[mCurSelectedTableColumn identifier] 
                                            forKey:kSortedTableColumn];
  [[NSUserDefaults standardUserDefaults] setBool:[mMessageListDataSource isSortedDescending]
                                          forKey:kIsMessageListSortedDescending];
  
  // Save the current open/close state of the message folders
  NSMutableDictionary* openStateDict = [[NSMutableDictionary alloc] init];
  MailboxItem* curMailboxItem = nil;
  NSEnumerator* mailboxesEnum = [[mMailboxesDataSource rootAccountFolderList] objectEnumerator];
  while ((curMailboxItem = [mailboxesEnum nextObject]))
  {
    [openStateDict setObject:[NSNumber numberWithBool:[mMailboxesOutlineView isItemExpanded:curMailboxItem]]
                      forKey:[NSString stringWithFormat:kMessageFolderIsOpenStateKeySuffix, [curMailboxItem name]]];
  }
  [[NSUserDefaults standardUserDefaults] setObject:openStateDict forKey:kMessageFolderOpenCloseDictionary];
  [openStateDict release];
    
  [[NSUserDefaults standardUserDefaults] synchronize];
}

-(void)windowWillClose:(NSNotification *)notification
{
  [self autosaveWindowFrame];
  // Perform any cleanup here.
}

#pragma mark -

-(IBAction)newMailMessage:(id)sender
{
  [[MessageComposeService sharedComposeService] createNewMessage];
}

-(IBAction)deleteMail:(id)sender
{
  if ([mMessagesTableView selectedRow] == -1)
    return;

  // Clear our message display
  [self clearMessageView];
  
  [mMessageListDataSource deleteMessages:[mMessagesTableView selectedRowIndexes]];
}

-(IBAction)reply:(id)sender
{
  NSString* messageUri = [mMessageListDataSource generateUriForMessageAtIndex:[mMessagesTableView selectedRow]];
  [[MessageComposeService sharedComposeService] replyToMessageUri:messageUri];
}

-(IBAction)replyAll:(id)sender
{
  NSString* messageUri = [mMessageListDataSource generateUriForMessageAtIndex:[mMessagesTableView selectedRow]];
  [[MessageComposeService sharedComposeService] replyToAllMessageUri:messageUri];
}

-(IBAction)foward:(id)sender
{
  NSString* messageUri = [mMessageListDataSource generateUriForMessageAtIndex:[mMessagesTableView selectedRow]];
  [[MessageComposeService sharedComposeService] forwardMessageUri:messageUri];
}

-(IBAction)sendReceive:(id)sender
{
  if (mCurMailboxItem)
    [[MessageWindowService sharedInstance] getNewMessagesForMailboxItem:mCurMailboxItem];
  else
    [[NotificationHandler sharedInstance] showSelectFolderNotice:[self window]];
  
  mIsGettingNewMail = YES;
  
  /*
   This requires a lot of syncing to work properly.... (maybe a new thread?)
   else
    [[MessageWindowService sharedInstance] getNewMessagesForMailboxItems:[[mMailboxesOutlineView dataSource] rootAccountFolderList]];
   */
}

-(IBAction)stop:(id)sender
{
  [[MessageWindowService sharedInstance] stopActiveUrl];
}

-(IBAction)reloadMessage:(id)sender
{
  if ([mMessagesTableView selectedRow] == -1)
    return;
  
  [mMessageListDataSource reloadCurrentMessage];
}

-(IBAction)openAddressBook:(id)sender
{
  [[AddressBookDlgController sharedInstance] showWindow:self];
}

-(IBAction)markSelectedMessagesRead:(id)sender
{
  if ([mMessagesTableView selectedRow] == -1)
    return;
  
  [mMessageListDataSource markMessageIndexes:[mMessagesTableView selectedRowIndexes] areRead:YES];
}

-(IBAction)markSelectedMessagesUnread:(id)sender
{
  if ([mMessagesTableView selectedRow] == -1)
    return;
  
  [mMessageListDataSource markMessageIndexes:[mMessagesTableView selectedRowIndexes] areRead:NO];
}

-(IBAction)markSelectedMessagesFlagged:(id)sender
{
  if ([mMessagesTableView selectedRow] == -1)
    return;
  
  [mMessageListDataSource markMessageIndexes:[mMessagesTableView selectedRowIndexes] areFlagged:YES];
}

-(IBAction)markSelectedMessagesUnflagged:(id)sender
{
  if ([mMessagesTableView selectedRow] == -1)
    return;
  
  [mMessageListDataSource markMessageIndexes:[mMessagesTableView selectedRowIndexes] areFlagged:NO];
}

-(IBAction)setViewLayout:(id)sender
{
  BOOL shouldBeVertical = ([mMessageSplitView isVertical] ? NO : YES);
  [mMessageSplitView setVertical:shouldBeVertical];
  [[self window] display];
}

-(BOOL)isTransmitting
{
  return mIsTransmitting;
}

-(NSString*)selectedAccountKey
{
  if (!mCurMailboxItem)
    return nil;
  
  return ([mCurMailboxItem isGroup] ? [mCurMailboxItem accountKey] : [[mCurMailboxItem parentMailbox] accountKey]);
}

-(void)refreshMailboxList
{
  // It would be cleaner if |MailboxesOutlineView| did this on reloadData.
  MailboxesDataSource* mailboxesDS = (MailboxesDataSource*)[mMailboxesOutlineView dataSource];
  [mailboxesDS rebuildFolderList];
  [mMailboxesOutlineView reloadData];
}

-(void)updateMessageDisplay
{
  [mNumMessagesField setIntValue:[mMessageListDataSource messageCount]];
  [mNumUnreadMessagesField setIntValue:[mMessageListDataSource unreadMessageCount]];
  
  [[self window] setTitle:[self formattedTitleWithCurrentFolder]];
}

-(NSString*)formattedTitleWithCurrentFolder
{
  return [NSString stringWithFormat:@"Correo - %@", [mCurMailboxItem name]];
}

-(void)clearMessageView
{
  [mBrowserView clearMessageView];
  [mCHBrowserView loadURI:@"about:blank"
                 referrer:nil 
                    flags:NSLoadFlagsNone 
              allowPopups:NO];
}

-(void)windowDidBecomeMain:(id)sender
{
  [[MessageWindowService sharedInstance] setMessageWindowDelegate:self];
}

-(void)windowDidResignMain:(id)sender
{
  [[MessageWindowService sharedInstance] setMessageWindowDelegate:nil];
}

-(void)openMessageInNewWindow:(id)sender
{
  if ([mMessagesTableView selectedRow] == -1)
    return;
  
  MessageHeader* messageHeader = [mMessageListDataSource messageHeaderAtIndex:[mMessagesTableView selectedRow]];
  NSString* uri = [mMessageListDataSource generateUriForMessageHeader:messageHeader];
  
  [[MessageWindowService sharedInstance] openMessageWindowWithMessageHeader:messageHeader
                                                                 messageUri:uri
                                                            andCharacterSet:[mCHBrowserView currentCharset]];
}

-(void)refreshMessageList
{
  [mMessagesTableView reloadData];
}

-(void)selectMessageIndexes:(NSIndexSet*)aIndexSet
{
  [mMessagesTableView selectRowIndexes:aIndexSet byExtendingSelection:NO];
  
  // Make sure that the message list service knows that we are selecting
  [mMessageListDataSource didSelectMessageRows:aIndexSet];
}

-(void)scrollMessagesToSelectRow:(unsigned int)aRowSelect
{
  [mMessagesTableView scrollRowToVisible:aRowSelect];
  [mMessagesTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:aRowSelect] byExtendingSelection:NO];
}

-(CompositionWindowController*)newCompositionController
{
  CompositionWindowController* composition = [[CompositionWindowController alloc] initWithWindowNibName:@"CompositionWindow"];
  return composition;
}

#pragma mark -

// 
// NSOutlineView Delegate Methods
//
- (BOOL)outlineView:(NSOutlineView *)inOutlineView shouldEditTableColumn:(NSTableColumn *)inTableColumn 
               item:(id)inItem
{
  return NO;
}

-(void)outlineView:(NSOutlineView*)inOutlineView 
   willDisplayCell:(NSCell*)inCell 
    forTableColumn:(NSTableColumn*)inTableColumn 
              item:(id)inItem
{ 
  if (inItem)
  {
    MailboxTextCell* cell = (MailboxTextCell*)inCell;
    [cell setImage:[inItem icon]];
    
    if ([inCell type] == NSTextCellType)
    {
      if ([inOutlineView selectedRow] == [inOutlineView rowForItem:inItem])
        [(id)inCell setTextColor:[NSColor whiteColor]];
      else
        [(id)inCell setTextColor:[NSColor blackColor]];
    }
  }
}

-(BOOL)outlineView:(NSOutlineView *)inOutlineView shouldSelectItem:(id)inItem
{
  if (mCurMailboxItem != inItem)
  {
    mCurMailboxItem = (MailboxItem*)inItem;
    [mMessagesTableView deselectAll:self];
  }
  
  if (![mCurMailboxItem isGroup])
  {
    [mMessageListDataSource loadMessagesForMailbox:mCurMailboxItem isUpdating:NO];
    [mMessagesTableView reloadData];
    [self updateMessageDisplay];
    [self clearMessageView];
  }
  
  return YES;
}

-(void)outlineViewSelectionDidChange:(NSNotification *)notification
{
  if ([mMailboxesOutlineView selectedRow] == -1)
  {
    [mMessageListDataSource clearMessages];
    [mMessagesTableView reloadData];
    [self clearMessageView];
  }
}

-(void)splitView:(NSSplitView *)sender resizeSubviewsWithOldSize:(NSSize)oldSize
{
  // keep the mailboxes outline view the same size...
  if (sender == mMailWindowSplitView)
  {
    NSView* left = [[sender subviews] objectAtIndex:0];        // get the two sub views
    NSView* right = [[sender subviews] objectAtIndex:1];
    float dividerThickness = [sender dividerThickness];         // and the divider thickness
    NSRect newFrame = [sender frame];                           // get the new size of the whole splitView
    NSRect leftFrame = [left frame];                            // current size of the left subview
    NSRect rightFrame = [right frame];                          // ...and the right
    leftFrame.size.height = newFrame.size.height;               // resize the height of the left
    leftFrame.origin = NSMakePoint(0,0);                        // don't think this is needed
     // the rest of the width...
    rightFrame.size.width = newFrame.size.width - leftFrame.size.width - dividerThickness;
    rightFrame.size.height = newFrame.size.height;              // the whole height
    rightFrame.origin.x = leftFrame.size.width + dividerThickness;  // 
    [left setFrame:leftFrame];
    [right setFrame:rightFrame];
  }
  else
  {
    [sender adjustSubviews];
  }
}

#pragma mark -

//
// NSTableView delegate methods
//
-(void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell 
  forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
  //XXX make font bold if unread?
}

-(BOOL)tableView:(NSTableView*)aTableView shouldSelectRow:(int)rowIndex
{
  [self updateMessageDisplay];
  
  return YES;
}

-(void)tableViewSelectionDidChange:(NSNotification*)aNotification
{
  if ([[mMessagesTableView selectedRowIndexes] count] > 1)
    [self clearMessageView];
  else
    [mMessageListDataSource didSelectMessageRows:[mMessagesTableView selectedRowIndexes]];
}

-(void)tableView:(NSTableView*)aTableView didClickTableColumn:(NSTableColumn*)aTableColumn
{
  NSString* identifier = [aTableColumn identifier];
  SEL sortSelector;
  
  //XXX it would be nice to have these as constants?
  if ([identifier isEqualToString:@"isFlagged"])
    sortSelector = @selector(compareIsFlagged:);
  else if ([identifier isEqualToString:@"isRead"])
    sortSelector = @selector(compareIsRead:);
  else if ([identifier isEqualToString:@"author"])
    sortSelector = @selector(compareAuthor:);
  else if ([identifier isEqualToString:@"subject"])
    sortSelector = @selector(compareSubject:);
  else if ([identifier isEqualToString:@"date"])
    sortSelector = @selector(compareDate:);
  else
    return; // avoid updating the table again.
  
  [mMessageListDataSource sortUsingSelector:sortSelector];
  [mMessagesTableView reloadData];
  [mMessagesTableView setHighlightedTableColumn:aTableColumn];
  
  // Reset the sort indicator.
  if (mCurSelectedTableColumn != nil || mCurSelectedTableColumn != aTableColumn)
    [mMessagesTableView setIndicatorImage:nil inTableColumn:mCurSelectedTableColumn];
  NSString* sortImage = [mMessageListDataSource isSortedDescending] ? @"NSDescendingSortIndicator" : @"NSAscendingSortIndicator";
  [mMessagesTableView setIndicatorImage:[NSImage imageNamed:sortImage] inTableColumn:aTableColumn];
  mCurSelectedTableColumn = aTableColumn;
}

#pragma mark -

-(BrowserTabView*)getTabBrowser
{
  return mTabBrowser;
}

-(BrowserWrapper*)getBrowserWrapper
{
  return nil;
  //return mBrowserWrapper;
}

-(void)createNewTab:(ENewTabContents)contents
{
  BrowserTabViewItem* newTab  = [self createNewTabItem];
  BrowserWrapper*     newView = [newTab view];
  
  BOOL loadHomepage = NO;
  if (contents == eNewTabHomepage)
  {
    // 0 = about:blank, 1 = home page, 2 = last page visited
    int newTabPage = [[PreferenceManager sharedInstance] getIntPref:"browser.tabs.startPage" withSuccess:NULL];
    loadHomepage = (newTabPage == 1);
  }
  
  [newTab setLabel: (loadHomepage ? NSLocalizedString(@"TabLoading", @"") : NSLocalizedString(@"UntitledPageTitle", @""))];
  [mTabBrowser addTabViewItem:newTab];
  
  BOOL focusURLBar = NO;
  if (contents != eNewTabEmpty)
  {
    NSString* urlToLoad = @"about:blank";
    [newView loadURI:urlToLoad referrer:nil flags:NSLoadFlagsNone focusContent:!focusURLBar allowPopups:NO];
  }
  
  [mTabBrowser selectLastTabViewItem:self];
}

-(BrowserTabViewItem*)createNewTabItem
{
  BrowserTabViewItem* newTab = [BrowserTabView makeNewTabItem];
  BrowserWrapper* newView = [[BrowserWrapper alloc] initWithTab:newTab inWindow:[self window]];
  [newView setUICreationDelegate:self];
  
  // size the new browser view properly up-front, so that if the
  // page is scrolled to a relative anchor, we don't mess with the
  // scroll position by resizing it later
  [newView setFrame:[mTabBrowser contentRect] resizingBrowserViewIfHidden:YES];
  
  [newTab setView: newView];  // takes ownership
  [newView release];
  
  // we have to copy the context menu for each tag, because
  // the menu gets the tab view item's tag.
  NSMenu* contextMenu = [mTabMenu copy];
  [[newTab tabItemContentsView] setMenu:contextMenu];
  [contextMenu release];
  
  return newTab;
}

-(void)openNewTabWithURL:(NSString*)aURLSpec referrer:(NSString*)aReferrer loadInBackground:(BOOL)aLoadInBG 
             allowPopups:(BOOL)inAllowPopups setJumpback:(BOOL)inSetJumpback
{
  BrowserTabViewItem* previouslySelected = (BrowserTabViewItem*)[mTabBrowser selectedTabViewItem];
  BrowserTabViewItem* newTab             = [self openNewTab:aLoadInBG];
  
  // if instructed, tell the tab browser to remember the currently selected tab to
  // jump back to if this new one is closed w/out switching to any other tabs.
  // This must come after the call to |openNewTab:| which clears the jumpback
  // tab and changes the selected tab to the new tab.
  if (inSetJumpback && !aLoadInBG)
    [mTabBrowser setJumpbackTab:previouslySelected];
  
  [[newTab view] loadURI:aURLSpec referrer:aReferrer flags:NSLoadFlagsNone focusContent:NO allowPopups:inAllowPopups];
}

-(BrowserTabViewItem*)openNewTab:(BOOL)aLoadInBG
{
  BrowserTabViewItem* newTab  = [self createNewTabItem];
  
  // hyatt originally made new tabs open on the far right and tabs opened from a content
  // link open to the right of the current tab. The idea was to keep the new tab
  // close to the tab that spawned it, since they are related. Users, however, got confused
  // as to why tabs appeared in different places, so now all tabs go on the far right.
#ifdef OPEN_TAB_TO_RIGHT_OF_SELECTED    
  NSTabViewItem* selectedTab = [mTabBrowser selectedTabViewItem];
  int index = [mTabBrowser indexOfTabViewItem: selectedTab];
  [mTabBrowser insertTabViewItem: newTab atIndex: index+1];
#else
  [mTabBrowser addTabViewItem: newTab];
#endif
  
  [newTab setLabel: NSLocalizedString(@"TabLoading", nil)];
  
  // unless we're told to load this tab in the bg, select the tab
  // before we load so that it's the primary and will push the url into
  // the url bar immediately rather than waiting for the server.
  if (!aLoadInBG)
    [mTabBrowser selectTabViewItem: newTab];
  
  return newTab;
}

#pragma mark -

-(void)willShowPromptForBrowser:(BrowserWrapper*)inBrowser
{
}

-(void)didDismissPromptForBrowser:(BrowserWrapper*)inBrowser
{
}

#pragma mark -

//
// MessageDataDelegate
//
-(void)onTotalMessagesChanged
{
  if (![[MessageWindowService sharedInstance] isTransmitting])
  {
    // Supress this message until the transmission is done.
    [mMessageListDataSource loadMessagesForMailbox:mCurMailboxItem isUpdating:YES];
    [self updateMessageDisplay];
  }
}

-(void)onTotalUnreadMessagesChanged
{
  [self updateMessageDisplay];
}

-(void)onNewMailBiffStateChanged
{
  [self updateMessageDisplay];
}

-(void)onStartTransmission
{
  mIsTransmitting = YES;
  [[[self window] toolbar] validateVisibleItems];
  [mProgressBar startAnimation:self];
}

-(void)onStopTransmission
{
  mIsTransmitting = NO;
  [[[self window] toolbar] validateVisibleItems];
  [mProgressBar stopAnimation:self];
  
  [mMessageListDataSource loadMessagesForMailbox:mCurMailboxItem isUpdating:YES];
  mShouldRefreshFolder = NO;
  
  [mMailboxesDataSource onStopTransmission];
  
  mIsGettingNewMail = NO;
}

-(void)onMessageLoaded:(DummyMessageHeader*)aDummyMessageHeader
{
  [mBrowserView updateViewForDummyHeader:aDummyMessageHeader];
  [mBrowserView showMessageHeaderView];
  [mBrowserView setBrowserViewActive:NO];
}

-(void)onStatusMessageUpdated:(NSString*)aStatusMessage
{
  // Note that this is using the localized gecko string... If we want to localize in the
  // future, we will need the string override service.
  [[self window] setTitle:[NSString stringWithFormat:@"%@ - %@", [self formattedTitleWithCurrentFolder], aStatusMessage]];
}

-(void)onAttachmentsLoaded:(NSArray*)aAttachmentArray
{
  if ([aAttachmentArray count] > 0)
    [mBrowserView showAttachmentView:aAttachmentArray];
  else
    [mBrowserView removeAttachmentView];
}

-(CHBrowserView*)browserMessageView
{
  return mCHBrowserView;
}

#pragma mark -

//
// BrowserUIDelegate methods
// XXX kreeger, let's see if these can enhance our UI for 0.3.
//
-(void)loadingStarted
{
}

-(void)loadingDone:(BOOL)activateContent
{
}

-(void)setLoadingActive:(BOOL)active
{
}

// a progress value of 0.0 will set the meter to its indeterminate state
-(void)setLoadingProgress:(float)progress
{
}

-(void)updateWindowTitle:(NSString*)title
{
}

-(void)updateStatus:(NSString*)status
{
}

-(void)updateLocationFields:(NSString*)url ignoreTyping:(BOOL)ignoreTyping
{
}

-(void)updateSiteIcons:(NSImage*)icon ignoreTyping:(BOOL)ignoreTyping
{
}

-(void)showPopupBlocked:(BOOL)blocked
{
}

-(void)configurePopupBlocking
{
}

-(void)unblockAllPopupSites:(nsIArray*)inSites
{
}

-(void)showSecurityState:(unsigned long)state
{
}

-(void)showFeedDetected:(BOOL)inDetected
{
}

-(BOOL)userChangedLocationField
{
  return NO;
}

-(void)contentViewChangedTo:(NSView*)inView forURL:(NSString*)inURL
{
}

#pragma mark -

-(void)setupToolbar
{
  NSToolbar* toolbar = [[[NSToolbar alloc] initWithIdentifier:kMailWindowToolbarIdentifier] autorelease];
  [toolbar setDelegate:self];
  [toolbar setAllowsUserCustomization:YES];
  [toolbar setAutosavesConfiguration:YES];
  [[self window] setToolbar:toolbar];
}

-(NSArray*)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
{
  return [NSArray arrayWithObjects:
    kNewMessageToolbarIdentifier,
    kDeleteMailToolbarIdentifier,
    kReplyToolbarIdentifier,
    kReplyAllToolbarIdentifier,
    kFowardToolbarIdentifier,
    kSendReceiveToolbarIdentifier,
    kStopToolbarIdentifier,
    kAddressBookToolbarIdentifier,
    NSToolbarPrintItemIdentifier,
    NSToolbarFlexibleSpaceItemIdentifier,
    NSToolbarSpaceItemIdentifier,
    NSToolbarSeparatorItemIdentifier,
    nil];
}

-(NSArray*)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
{
  return [NSArray arrayWithObjects:
    kNewMessageToolbarIdentifier,
    kDeleteMailToolbarIdentifier,
    NSToolbarSpaceItemIdentifier,
    kReplyToolbarIdentifier,
    kReplyAllToolbarIdentifier,
    kFowardToolbarIdentifier,
    NSToolbarSpaceItemIdentifier,
    kSendReceiveToolbarIdentifier,
    kStopToolbarIdentifier,
    NSToolbarSpaceItemIdentifier,
    NSToolbarPrintItemIdentifier,
    nil];
}

-(NSToolbarItem*) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
  NSToolbarItem *theItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease];
  
  if ([itemIdentifier isEqualToString:kNewMessageToolbarIdentifier]) 
  {
    [theItem setLabel:NSLocalizedString(@"NewMessage", nil)];
    [theItem setToolTip:NSLocalizedString(@"NewMessageToolTip", nil)];
    [theItem setPaletteLabel:NSLocalizedString(@"NewMessageButton", nil)];
    [theItem setAction:@selector(newMailMessage:)];
    [theItem setImage:[NSImage imageNamed:@"document_edit.tif"]];
  }
  else if ([itemIdentifier isEqualToString:kDeleteMailToolbarIdentifier])
  {
    [theItem setLabel:NSLocalizedString(@"Delete", nil)];
    [theItem setToolTip:NSLocalizedString(@"DeleteMailToolTip", nil)];
    [theItem setPaletteLabel:NSLocalizedString(@"DeleteButton", nil)];
    [theItem setAction:@selector(deleteMail:)];
    [theItem setImage:[NSImage imageNamed:@"trash.tif"]];
  }
  else if ([itemIdentifier isEqualToString:kReplyToolbarIdentifier])
  {
    [theItem setLabel:NSLocalizedString(@"Reply", nil)];
    [theItem setToolTip:NSLocalizedString(@"ReplyToolTip", nil)];
    [theItem setPaletteLabel:NSLocalizedString(@"ReplyButton", nil)];
    [theItem setAction:@selector(reply:)];
    [theItem setImage:[NSImage imageNamed:@"circle_return.tif"]];
  }
  else if ([itemIdentifier isEqualToString:kReplyAllToolbarIdentifier])
  {
    [theItem setLabel:NSLocalizedString(@"ReplyAll", nil)];
    [theItem setToolTip:NSLocalizedString(@"ReplyAllToolTip", nil)];
    [theItem setPaletteLabel:NSLocalizedString(@"ReplyAllButton", nil)];
    [theItem setAction:@selector(replyAll:)];
    [theItem setImage:[NSImage imageNamed:@"circle_turnright.tif"]];
  }
  else if ([itemIdentifier isEqualToString:kFowardToolbarIdentifier])
  {
    [theItem setLabel:NSLocalizedString(@"Foward", nil)];
    [theItem setToolTip:NSLocalizedString(@"FowardToolTip", nil)];
    [theItem setPaletteLabel:NSLocalizedString(@"FowardButton", nil)];
    [theItem setAction:@selector(foward:)];
    [theItem setImage:[NSImage imageNamed:@"forward.tif"]];
  }
  else if ([itemIdentifier isEqualToString:kSendReceiveToolbarIdentifier])
  {
    [theItem setLabel:NSLocalizedString(@"SendReceive", nil)];
    [theItem setToolTip:NSLocalizedString(@"SendReceiveToolTip", nil)];
    [theItem setPaletteLabel:NSLocalizedString(@"SendReceiveButton", nil)];
    [theItem setAction:@selector(sendReceive:)];
    [theItem setImage:[NSImage imageNamed:@"getmail1.tif"]];
  }
  else if ([itemIdentifier isEqualToString:kStopToolbarIdentifier])
  {
    [theItem setLabel:NSLocalizedString(@"Stop", nil)];
    [theItem setToolTip:NSLocalizedString(@"StopToolTip", nil)];           
    [theItem setPaletteLabel:NSLocalizedString(@"StopButton", nil)];
    [theItem setAction:@selector(stop:)];
    [theItem setImage:[NSImage imageNamed:@"stop.tif"]];
  }
  else if ([itemIdentifier isEqualToString:kAddressBookToolbarIdentifier])
  {
    [theItem setLabel:NSLocalizedString(@"AddressBook", nil)];
    [theItem setToolTip:NSLocalizedString(@"AddressBookToolTip", nil)];
    [theItem setPaletteLabel:NSLocalizedString(@"AddressBookButton", nil)];
    [theItem setAction:@selector(openAddressBook:)];
    [theItem setImage:[NSImage imageNamed:@"address_book.tif"]];
  }
  
  // Something strange, return nil
  else
    return nil;
  
  return theItem;
}

-(BOOL)validateToolbarItem:(NSToolbarItem *)theItem
{
  return [self shouldEnableItemWithSelector:[theItem action]];
}

#pragma mark -

-(BOOL)shouldEnableItemWithSelector:(SEL)aSelector
{
  if (aSelector == @selector(sendReceive:) && mIsTransmitting)
    return NO;
  
  else if (aSelector == @selector(stop:) && !mIsTransmitting)
    return NO;
  
  else if (aSelector == @selector(openAccountManager:) || aSelector == @selector(newMailAccount:))
    return YES;
  
  else if (![[MessageAccountManager sharedInstance] accountsExist])
    return NO;
  
  return YES;
}

-(NSRect)calcFrameForWidth:(float)aWidth andFrame:(NSRect)aFrame
{
  if (aWidth > 0)
    aFrame.size.width = aWidth;
  
  return aFrame;
}

@end


@implementation StatusBarView

-(void)drawRect:(NSRect)aRect
{
  [super drawRect:aRect];
  [[NSColor controlHighlightColor] set];
  NSRectFill(aRect);
}

@end

